/**
 * @file     any_type.hpp
 * @author   WMQ
 * @date     2024/10/21
 * @brief    any类型的简单实现，C++17可以使用std::any
 */

#ifndef ANY_TYPE_HPP
#define ANY_TYPE_HPP

#include <type_traits>
#include <utility>

/**
 * @brief AnyType类型，存储任意类型变量值
 */
class AnyType
{
public:
    /**
     * @brief 包装模板类的基类
     */
    class BaseObject
    {
    public:
        BaseObject() = default;
        virtual ~BaseObject() = default;
        /**
         * @brief 创建BaseObject子类对象的副本
         * @return
         *  返回一个指向BaseObject子类对象的BaseObject类指针 \n
         */
        virtual BaseObject* Copy() = 0;
    };

    /**
     * @brief 具体类型的包装模板类
     *
     * ValueType不能为引用类型，注意使用std::remove_reference移除引用
     */
    template <typename ValueType>
    class ValueWrapper : public BaseObject
    {
    public:
        explicit ValueWrapper(ValueType &value) : value_(value) {}

        explicit ValueWrapper(ValueType &&value) : value_(std::move(value)) {}

        ValueWrapper(const ValueWrapper &value_obj) : value_(value_obj.value_) {}

        ValueWrapper &operator=(const ValueWrapper &) = delete;

        ~ValueWrapper() override {}

        /**
         * @brief 创建对象副本
         * @return
         *  返回一个指向副本对象的BaseObject类指针 \n
         */
        BaseObject* Copy() override
        {
            return new ValueWrapper(*this);
        }

        ValueType value_; /**< 具体类型变量 */
    };

    /**
     * @brief 一般构造函数
     * @pre ValueType的退化类型不能为AnyType类型
     * @param[in] value 要复制保存的变量
     */
    template <
        typename ValueType,
        typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, AnyType>::value,
                                int>::type = 0>
    explicit AnyType(ValueType &&value)
    {
        // 要移除ValueType的引用
        object_ptr_ = new ValueWrapper<typename std::remove_reference<ValueType>::type>(
            std::forward<ValueType>(value));
    }

    AnyType() = default;

    /**
     * @brief 拷贝构造函数
     * @param[in] any AnyType类型变量
     */
    AnyType(const AnyType &any)
    {
        if (nullptr != any.object_ptr_)
        {
            object_ptr_ = any.object_ptr_->Copy();
        }
    }

    /**
     * @brief 移动构造函数
     * @param[in] any AnyType类型变量
     */
    AnyType(AnyType &&any) noexcept
    {
        object_ptr_ = any.object_ptr_;
        any.object_ptr_ = nullptr;
    }

    /**
     * @brief 拷贝赋值函数
     * @param[in] any AnyType类型变量
     * @note
     * 不考虑自我赋值
     */
    AnyType &operator=(const AnyType &value)
    {
        delete object_ptr_;
        object_ptr_ = nullptr;
        if (nullptr != value.object_ptr_)
        {
            object_ptr_ = value.object_ptr_->Copy();
        }
        return *this;
    }

    /**
     * @brief 移动赋值函数
     * @param[in] any AnyType类型变量
     * @note
     * 不考虑自我移动
     */
    AnyType &operator=(AnyType &&value) noexcept
    {
        delete object_ptr_;
        object_ptr_ = value.object_ptr_;
        value.object_ptr_ = nullptr;
        return *this;
    }

    /**
     * @brief 重载赋值运算符
     * @pre ValueType的退化类型不能为AnyType类型
     * @param[in] value 要复制保存的变量
     */
    template <
        typename ValueType,
        typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, AnyType>::value,
                                int>::type = 0>
    AnyType &operator=(ValueType &&value)
    {
        delete object_ptr_;
        object_ptr_ = new ValueWrapper<typename std::remove_reference<ValueType>::type>(
            std::forward<ValueType>(value));
        return *this;
    }

    ~AnyType()
    {
        delete object_ptr_;
    }

    /**
     * @brief 动态转换
     * @return
     *  动态转换为指定类型: 失败返回空指针，成功返回指向该变量的指针
     */
    template <typename ValueType>
    ValueType* DynamicCast()
    {
        ValueWrapper<ValueType>* ptr = dynamic_cast<ValueWrapper<ValueType>*>(object_ptr_);
        return ptr ? &(ptr->value_) : nullptr;
    }

private:
    BaseObject* object_ptr_ = nullptr; /**< 值包装对象指针 */
};

#endif